using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace NativeTest
{
    public static class NativePlugin
    {
        // Fields
        private static ManageLogDelegate debugLogFunc = null;
        private static ManageLogDelegate debugLogFuncError = null;
        private static ManageLogDelegate debugLogFuncWarnning = null;
        private static object s_LockObj_hash = new object();
        private static Regex s_regex = new Regex(",+\"res\":-?\\d+|\"res\":-?\\d+,+", RegexOptions.Compiled);
        private static byte[] sessionCode;
        public static string svnRevision = string.Empty;

        // Methods
        public static void breakData(byte[] data, bool isData)
        {
            object obj2 = s_LockObj_hash;
            lock (obj2)
            {
                GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
                breakData_(handle.AddrOfPinnedObject(), data.Length, !isData ? 60 : 0xdd);
                handle.Free();
            }
        }

        [DllImport("ChronicleNUtils")]
        private static extern byte breakData_(IntPtr data, int data_size, int bd);

        public static bool CheckHashM(string serverHash, string data)
        {
            object obj2 = s_LockObj_hash;
            lock (obj2)
            {
                string s = s_regex.Replace(data, string.Empty);
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                byte[] buffer2 = Convert.FromBase64String(serverHash);
                GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                GCHandle handle2 = GCHandle.Alloc(buffer2, GCHandleType.Pinned);
                IntPtr ptr = handle.AddrOfPinnedObject();
                IntPtr ptr2 = handle2.AddrOfPinnedObject();
                int num = Native_CheckHashM(ptr, bytes.Length, ptr2, buffer2.Length);
                handle.Free();
                handle2.Free();
                return (num != -1);
            }
        }

        public static string GetHashCd(string str, string tm)
        {
            object obj2 = s_LockObj_hash;
            lock (obj2)
            {
                string s = str + "&timestamp=" + tm;
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                byte[] buffer2 = new byte[20];
                GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                GCHandle handle2 = GCHandle.Alloc(buffer2, GCHandleType.Pinned);
                IntPtr data = handle.AddrOfPinnedObject();
                IntPtr ptr2 = handle2.AddrOfPinnedObject();
                Native_GetHashCd(data, bytes.Length, ptr2, buffer2.Length);
                handle.Free();
                handle2.Free();
                return Convert.ToBase64String(buffer2);
            }
        }

        public static string GetHashCh(string str, string tm)
        {
            object obj2 = s_LockObj_hash;
            lock (obj2)
            {
                string s = str + "&timestamp=" + tm;
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                byte[] buffer2 = new byte[20];
                GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                GCHandle handle2 = GCHandle.Alloc(buffer2, GCHandleType.Pinned);
                IntPtr data = handle.AddrOfPinnedObject();
                IntPtr ptr2 = handle2.AddrOfPinnedObject();
                Native_GetHashCh(data, bytes.Length, ptr2, buffer2.Length);
                handle.Free();
                handle2.Free();
                return Convert.ToBase64String(buffer2);
            }
        }

        public static string GetHashEn(string str, string tm)
        {
            object obj2 = s_LockObj_hash;
            lock (obj2)
            {
                string s = str + "&timestamp=" + tm;
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                byte[] buffer2 = new byte[20];
                GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                GCHandle handle2 = GCHandle.Alloc(buffer2, GCHandleType.Pinned);
                IntPtr data = handle.AddrOfPinnedObject();
                IntPtr ptr2 = handle2.AddrOfPinnedObject();
                Native_GetHashEn(data, bytes.Length, ptr2, buffer2.Length);
                handle.Free();
                handle2.Free();
                return Convert.ToBase64String(buffer2);
            }
        }

        public static string getWebClientString()
        {
            object obj2 = s_LockObj_hash;
            lock (obj2)
            {
                StringBuilder build = new StringBuilder(0x40);
                getWebClientString(build, build.Capacity);
                return build.ToString();
            }
        }

        [DllImport("ChronicleNUtils")]
        private static extern void getWebClientString([In, Out] StringBuilder build, int size);

        public static void InitBreakKey()
        {
        }

        public static void initializeNative(string s)
        {
        }

        [DllImport("ChronicleNUtils")]
        private static extern void initializeNative(IntPtr data, int data_size);

        [DllImport("ChronicleNUtils")]
        private static extern int loadFile(string path, IntPtr data, int data_size);

        public static string makeWebClientString(string str)
        {
            byte[] buffer = new byte[0x400];
            GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            IntPtr data = handle.AddrOfPinnedObject();
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            GCHandle handle2 = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            IntPtr ptr2 = handle2.AddrOfPinnedObject();
            int num = makeWebClientString(data, buffer.Length, ptr2, bytes.Length);
            handle.Free();
            handle2.Free();
            Array.Resize<byte>(ref buffer, num);
            return Encoding.UTF8.GetString(buffer);
        }

        [DllImport("ChronicleNUtils")]
        private static extern int makeWebClientString(IntPtr data, int data_size, IntPtr hash_data, int hash_size);

        [DllImport("ChronicleNUtils")]
        private static extern int Native_CheckHashM(IntPtr data, int data_size, IntPtr hash_data, int hash_size);

        [DllImport("ChronicleNUtils")]
        private static extern void Native_GetHashCd(IntPtr data, int data_size, IntPtr hash_data, int hash_size);

        [DllImport("ChronicleNUtils")]
        private static extern void Native_GetHashCh(IntPtr data, int data_size, IntPtr hash_data, int hash_size);

        [DllImport("ChronicleNUtils")]
        private static extern void Native_GetHashEn(IntPtr data, int data_size, IntPtr hash_data, int hash_size);

        public static byte[] ReadBinary(string path)
        {
            FileInfo info = new FileInfo(path);
            int length = (int)info.Length;
            byte[] buffer = new byte[length];
            GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            IntPtr data = handle.AddrOfPinnedObject();
            int num2 = loadFile(path, data, length);
            handle.Free();
            if (num2 < 0)
            {
                if (debugLogFuncError != null)
                {
                    object[] objArray1 = new object[] { "ReadBinary() file load error. code:", num2, "  path:", path };
                    debugLogFuncError(string.Concat(objArray1));
                }
                return null;
            }
            if (buffer == null)
            {
                if (debugLogFuncError != null)
                {
                    object[] objArray2 = new object[] { "ReadBinary() dst_buf null. code:", num2, "  path:", path };
                    debugLogFuncError(string.Concat(objArray2));
                }
                return null;
            }
            Array.Resize<byte>(ref buffer, num2);
            if (buffer != null)
            {
                return buffer;
            }
            if (debugLogFuncError != null)
            {
                object[] objArray3 = new object[] { "ReadBinary() dst_buf null............... code:", num2, "  path:", path };
                debugLogFuncError(string.Concat(objArray3));
            }
            return null;
        }

        [DllImport("ChronicleNUtils")]
        private static extern int saveFile(string path, IntPtr data, int data_size);

        [DllImport("ChronicleNUtils")]
        public static extern int scrambleStringFunc(IntPtr dst, int dst_buf_size, IntPtr src, int src_buf_size);

        [DllImport("ChronicleNUtils")]
        private static extern void sessionInitialize([In] IntPtr sid, [In] int len, [In] int uid);

        [DllImport("ChronicleNUtils")]
        private static extern void sessionInitializeDelete();

        [DllImport("ChronicleNUtils")]
        private static extern void setLogDelegate(IntPtr func);

        [DllImport("ChronicleNUtils")]
        private static extern void setLogErrorDelegate(IntPtr func);

        [DllImport("ChronicleNUtils")]
        private static extern void setLogWarnningDelegate(IntPtr func);

        public static void TerminateBreakKey()
        {
        }

        public static void updateSID(byte[] sid, int uid)
        {
            if (sid != null)
            {
                GCHandle handle = GCHandle.Alloc(sid, GCHandleType.Pinned);
                sessionInitialize(handle.AddrOfPinnedObject(), sid.Length, uid);
                handle.Free();
            }
            else
            {
                IntPtr ptr2 = new IntPtr();
                sessionInitializeDelete();
            }
        }

        public static void WriteBinary(string path, byte[] data)
        {
            if (data != null)
            {
                GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
                IntPtr ptr = handle.AddrOfPinnedObject();
                saveFile(path, ptr, data.Length);
                handle.Free();
            }
        }

        public static byte[] DecodeRotData(byte[] from)
        {
            int num = from[0];
            int num2 = from.Length - (4 + (4 - ((num == 0) ? 4 : num)));
            byte[] buffer = new byte[num2];
            DecodeRotData_native(buffer, buffer.Length, from);
            return buffer;
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("ChronicleNUtils", EntryPoint = "DecodeRotData")]
        private static extern void DecodeRotData_native([Out] byte[] dst_buf, [In] int dst_size, [In] byte[] from_buf);

        public static bool DecodeXorData(ref byte[] from)
        {
            if (from.Length <= 8)
            {
                return false;
            }
            return DecodeXorData_native(from, from.Length);
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("ChronicleNUtils", EntryPoint = "DecodeXorData")]
        private static extern bool DecodeXorData_native([In, Out] byte[] from, [In] int from_size);


        // Nested Types
        public delegate void ManageLogDelegate(string log);
    }
}